package com.jse;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import com.jse.json.JsonObject;

public class Trees {

	private static Comparator<Map<String,Object>> comparator = new Comparator<Map<String,Object>>() {
        public int compare(Map<String,Object> rp1, Map<String,Object> rp2) {
            return rp1.get("pid").toString().compareTo(rp2.get("pid").toString());
        }
    };

    /** 
     * 
     * @param list 所有元素的平级集合，map包含id和pid 
     * @param pid 顶级节点的pid，可以为null 
     * @param idName id位的名称，一般为id或者code 
     * @return 树 
     */  
    public static List<Map<String, Object>> getTree(List<Map<String, Object>> list, String pid, String idName) {  
        List<Map<String, Object>> res = new ArrayList<Map<String,Object>>();  
        if (list!=null&&list.size()>0)  
            for (Map<String, Object> map : list) {  
                if(pid.equals("0")|| map.get("p"+idName).toString().equals(pid)){  
                    String id = map.get(idName).toString();  
                    map.put("children", getTree(list, id, idName));  
                    res.add(map);  
                }  
            }  
        return res;  
    }  
    
    static List<Map> menu;
      
    public static List<Object> menus(List<Map> menu){   
    	return menus(menu,"0"); 
    } 
    public static List<Object> menus(List<Map> menu,String id){   
    	return menus(menu,id,null); 
    } 
    public synchronized static List<Object> menus(List<Map> menu,Object key,Map<String,Object> conf){   
    	if(conf==null)conf=new LinkedHashMap<>();
    	String id=conf.containsKey("id")?conf.get("id").toString():"id";
    	String pid=conf.containsKey("pid")?conf.get("pid").toString():"pid";
    	String children=conf.containsKey("children")?conf.get("children").toString():"children";
    	Trees.menu=menu;
    	List<Object> list = new ArrayList<Object>(); 
    	if(menu!=null)
      for (Map<String,Object> x : menu) {   
        Map<String,Object> mapArr = new LinkedHashMap<>();
        if(x.get(pid)==key||x.get(pid).toString().equals(key.toString())){ 
          mapArr.putAll(x);
          List<?> tlist=menuChild(x.get(id),pid);
          if(tlist.size()>0) {
        	  mapArr.put(children,tlist);  
          }
          list.add(mapArr); 
        } 
      }   
      return list; 
    } 
     
    public static List<?> menuChild(Object id,String pid){ 
      List<Object> lists = new ArrayList<Object>(); 
      for(Map<String,Object> a:menu){ 
        Map<String,Object> childArray = new LinkedHashMap<>();
        if(id!=null&&a!=null&&id.toString().equals(a.get(pid).toString())){
        	childArray.putAll(a);
          List<?> tlist=menuChild(a.get("id").toString(),pid);
          if(tlist.size()>0) {
        	  childArray.put("children", menuChild(a.get("id").toString(),pid));
          }
          lists.add(childArray); 
        } 
      } 
      return lists; 
    } 
    
    public static List<Map<String,Object>> toTree(List<Map<String,Object>> params) {
        List<Map<String,Object>> nodes = null;
        if (params.size() > 0) {
            //优先级排序
            Collections.sort(params, comparator);
            nodes = toTree(params, 0);
        }
        return nodes;
    }

    public static List<Map<String,Object>> toTreeLevel(List<Map<String,Object>> params, int level) {
        List<Map<String,Object>> nodes = null;
        if (params.size() > 0) {
            //优先级排序
            Collections.sort(params, comparator);
            nodes = toTreeLevel(params, 0, level);
        }
        return nodes;
    }

    /**
     * 无限级树形结构
     *
     * @param params params
     * @param pid    pid
     * @return list
     */
    public static List<Map<String,Object>> toTree(List<Map<String,Object>> params, long pid) {
        List<Map<String,Object>> nodes = new ArrayList<>();
        if (params != null && params.size() > 0) {
            for (int i = 0; i < params.size(); i++) {
            	Map<String,Object> node =params.get(i);
                if (Long.valueOf(node.get("pid").toString()) == pid) {
                    
                    //params.remove(i);
                    node.put("children",toTree(params, Long.valueOf(node.get("pid").toString())));
                    nodes.add(node);
                    i--;
                }
            }
        }
        return nodes;
    }

    /**
     * 两级树形数据
     *
     * @param params params
     * @param pid    pid
     * @param level  level
     * @return list
     */
    public static List<Map<String,Object>> toTreeLevel(List<Map<String,Object>> params, long pid, int level) {
        List<Map<String,Object>> nodes = new ArrayList<>();
        if (params != null && params.size() > 0) {
        	Map<String,Object> node = null;//当前节点
            for (int i = 0; i < params.size(); i++) {
                node = params.get(i);
                if (Long.valueOf(node.get("id").toString()) == pid) {
                    nodes.add(node);
                    params.remove(i);
                    if (level > 1) {
                        node.put("children",toTreeLevel(params, Long.valueOf(node.get("pid").toString()), --level));
                    } else {
                        nodes.addAll(toTreeLevel(params, Long.valueOf(node.get("pid").toString()), --level));
                    }
                    level++;
                    i--;
                }
            }
        }
        return nodes;
    }

  //非递归遍历文件夹
  	public static List<Object> ftree(String path,String...dirs){
  		  List<String> filters=Arrays.asList(dirs);
          LinkedList<JsonObject> list = new LinkedList<>();
          List<Map> list1 = new ArrayList<>();
          JsonObject dir = new JsonObject();
          File f=new File(path);
          dir.put("path",path);
          dir.put("name","/");
          dir.put("url","/");
          dir.put("pid", 0);
          dir.put("id", 1);
          dir.put("suffix","");
          dir.put("type", "dir");
          dir.put("file", f);
          list1.add(dir);
          int index = 1;
          File file[] = f.listFiles();
          for (int i = 0; i < file.length; i++) {
        	if(filters.contains(file[i].getName()))continue;
        	JsonObject tem  = new JsonObject();
        	tem.put("file", file[i]);
        	tem.put("path",file[i].getAbsolutePath());
        	tem.put("url","/"+file[i].getName());
          	tem.put("name",file[i].getName());
          	tem.put("id",++index);
          	tem.put("pid",dir.get("id"));
              if (file[i].isDirectory()){
              	tem.put("type", "dir");
              	tem.put("suffix","");
                  list.add(tem);
                  }
              else{
              	tem.put("type", "file");
              	tem.put("suffix",Fs.suffix(file[i].getName()));
          }
              list1.add(tem);
          }
          JsonObject tmp;
          while (!list.isEmpty()) {
              tmp = list.removeFirst();
              if (new File(tmp.get("path").toString()).isDirectory()) {
                  file = new File(tmp.get("path").toString()).listFiles();
                  if (file == null)
                      continue;
                  for (int i = 0; i < file.length; i++) {
                	JsonObject tem =new JsonObject();
                	tem.put("path",file[i].getAbsolutePath());
                  	tem.put("name",file[i].getName());
                  	tem.put("url",tmp.get("url").toString()+"/"+file[i].getName());
                  	tem.put("file",file[i]);
                  	tem.put("pid",tmp.get("id"));
                  	tem.put("id",++index);
                      if (file[i].isDirectory()) {
                    	  tem.put("type", "dir");
                    	  tem.put("suffix","");
                          list.add(tem);
                      }else{
                    	  tem.put("suffix",Fs.suffix(file[i].getName()));
                      	tem.put("type", "file");
                      }
                      list1.add(tem);
                      }
              }
          }
          return Trees.menus(list1);
  	}
}
